/*
 *      libidxp.h
 *      
 *      Copyright 2009 Daniele Ricci <denn86@gmail.com>, Luca Saccagi <luksak86@gmail.com>
 *      
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */
/*
 * version: 0.0.5
*/

#ifndef _LIBIDXP
#define _LIBIDXP


//################################################ INCLUDE
#include <vortex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <assert.h>
#include <dirent.h>
#include <time.h>
#include <winf.h>
#else
#include <sys/types.h>
#include <sys/dir.h>
#endif
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/valid.h>
#include "debug.h"

//################################################ DEFINE
#ifdef _WIN32
#define EXPORT __declspec(dllexport)
#else
#define EXPORT 
#endif

#define NEXT next
#define CHILDREN children
#define CONTENT children->content
#define PROPERTIES properties->CONTENT

#define PLAIN_PROFILE "http://fact.aspl.es/profiles/plain_profile" 
#define IDXP_PROFILE "http://idxp.org/beep/profile"
#define TLS_PROFILE "http://iana.org/beep/TLS"

#define MAX_STRING_SIZE 200
#define MAX_CONNECTIONS 200
#ifdef _WIN32
#define CLOSING_POLLING 100
#else
#define CLOSING_POLLING 100
#endif
#define TIMEOUTS 10

/* Validation Settings, Flags & defines */
#define NO_VALIDATION 0
#define WEAK_VALIDATION 1
#define STRONG_VALIDATION 2
#define FLAG_GREETING "<IDXP-Greeting"
#define FLAG_ALERT "<IDMEF-Message"
#define FLAG_HEARTBEAT "<IDMEF-Message"
#define FLAG_CONFIG "<Config>"
#define FLAG_EXTENDED "<Extended>"
static int xml_validation = WEAK_VALIDATION;

#define INITIATOR 1
#define LISTENER 0
#define BOTH 2
#define IDXPLIB_LISTENER idxp_initialization(LISTENER);
#define IDXPLIB_INITIATOR idxp_initialization(INITIATOR);
#define IDXPLIB idxp_initialization(BOTH);

#define IDXPROLE_HC 0
#define IDXPROLE_HS 1
#define IDXPROLE_AC 2
#define IDXPROLE_AS 3
#define IDXPROLE_CC 4
#define IDXPROLE_CS 5
#define IDXPROLE_EC 6
#define IDXPROLE_ES 7


//################################################ STRUCT
typedef long int lint;
typedef const char cchar;

typedef xmlDtdPtr IdxpDtd;
//typedef axlDtd *IdxpDtd;
typedef VortexFrame IdxpFrame;
typedef VortexConnection IdxpConnection;
typedef VortexChannel IdxpChannel;

typedef struct _srv_list{
	char ip[100];
	struct _srv_list *next;	
}srv_list;

typedef struct ext_time{
	char *hexstr;
	struct tm *t;
} extTime;

typedef struct _IdxpPeer {
	VortexChannel *ch;
	VortexConnection *cn;
	int channel_type;
	struct _IdxpPeer *next;
	struct _IdxpPeer *prev;
} IdxpPeer;

typedef struct _frame_handlers {
	bool (*heartbeat_client)();
	bool (*heartbeat_server)();
	bool (*alert_client)();
	bool (*alert_server)();
	bool (*config_client)();
	bool (*config_server)();
	bool (*extended_client)();
	bool (*extended_server)();
} frame_handlers;

typedef struct _greeting_properties {
	char uri[MAX_STRING_SIZE];
	char role[MAX_STRING_SIZE];
	char fqdn[MAX_STRING_SIZE];
	char streamt[MAX_STRING_SIZE];
}IdxpGreeting;

typedef struct _idxp_conf {
	char dtd_greeting[100];
	char dtd_idmef[100];
	char usr[100];
	char pw[100];
	char certificate[100];
	char certificate_key[100];
	char analyzer_id[100];
	char myuri[100];
	char fqdn[100];
	char srv_port[100];
	srv_list *top;
	bool loop;
	int cnt_index;
	int interval;
	struct _idxp_conf *next; //utilizzato??? comunque gestito sia dalla idxp_configuration_new sia dalla free.
	bool tls_enable;
	bool proceed_on_tls_fail;
}IdxpConfiguration;

//################################################ GLOBAL VAR
axlHash *connection_hash;
VortexMutex mutex;
VortexMutex mutex2;
VortexMutex timeout_writing;
VortexMutex channel_data;
VortexMutex dtd_validating;
bool *sgreet;
bool hb_rpy;
bool srv_is_down;
int hb_timeouts[MAX_CONNECTIONS];
int hb_cnt = 0;

frame_handlers framehan;
IdxpConfiguration *IDXPCONF;
IdxpDtd dtd_idmef;
IdxpDtd dtd_greeting;
IdxpPeer *peer_list;

/* 
	LIBIDXP 0.0.5 API
*/
EXPORT void idxp_initialization(int idxp_side);
EXPORT void idxp_exit(void);
//Configuration Related Functions
EXPORT IdxpConfiguration *idxp_configuration_new(void);
EXPORT void idxp_configuration_free(IdxpConfiguration *configuration);
EXPORT bool idxp_configuration_load(char *configuration_path, IdxpConfiguration *idxp_config);
EXPORT char *idxp_configuration_get(char *parm_name, IdxpConfiguration *idxp_config);
EXPORT void idxp_configuration_set(char *parm_name,char *parm_val, IdxpConfiguration *idxp_config);
//Custom frame_handlers Related Functions
EXPORT void idxp_custom_heartbeat_client_set(bool (*function)(IdxpConnection *connection,IdxpChannel *channel,IdxpFrame *frame,axlPointer user_data));
EXPORT void idxp_custom_heartbeat_server_set(bool (*function)(IdxpConnection *connection,IdxpChannel *channel,IdxpFrame *frame,axlPointer user_data));
EXPORT void idxp_custom_alert_client_set(bool (*function)(IdxpConnection *connection,IdxpChannel *channel,IdxpFrame *frame,axlPointer user_data));
EXPORT void idxp_custom_alert_server_set(bool (*function)(IdxpConnection *connection,IdxpChannel *channel,IdxpFrame *frame,axlPointer user_data));
EXPORT void idxp_custom_config_client_set(bool (*function)(IdxpConnection *connection,IdxpChannel *channel,IdxpFrame *frame,axlPointer user_data));
EXPORT void idxp_custom_config_server_set(bool (*function)(IdxpConnection *connection,IdxpChannel *channel,IdxpFrame *frame,axlPointer user_data));
EXPORT void idxp_custom_extended_client_set(bool (*function)(IdxpConnection *connection,IdxpChannel *channel,IdxpFrame *frame,axlPointer user_data));
EXPORT void idxp_custom_extended_server_set(bool (*function)(IdxpConnection *connection,IdxpChannel *channel,IdxpFrame *frame,axlPointer user_data));


//Greeting Related Functions
EXPORT char *idxp_greeting_set(char mygreet[1000],cchar *role,cchar* uri,cchar *fqdn,cchar *stype);
EXPORT IdxpGreeting *idxp_greeting_get(char *greet);
EXPORT bool idxp_greeting_send_and_wait(IdxpChannel *channel,cchar *role,cchar *streamtype, bool explicit_call);
//DTD Related Functions
EXPORT void idxp_dtd_init(void);
EXPORT IdxpDtd idxp_dtd_load(const char *dtd);
EXPORT void idxp_dtd_free(IdxpDtd dtd);
EXPORT bool idxp_dtd_validate_frame(IdxpFrame *frame,IdxpDtd dtd,char *firstflag);
EXPORT bool idxp_dtd_validate_buffer(char *buffer,IdxpDtd dtd);
//Connection & Channel Related Functions
EXPORT void idxp_listener_wait(void);
EXPORT IdxpConnection *idxp_connection_new(IdxpConnection *connection, char *host, char *port);
EXPORT IdxpConnection *idxp_connection_start(IdxpConnection *cn,cchar *host,cchar *port,cchar *usr,cchar *pw);
EXPORT IdxpChannel *idxp_channel_new(IdxpConnection *cn,int chNum,cchar *srvName,bool set_piggyback,cchar *role,cchar *uri,cchar *fqdn,cchar *streamType);
EXPORT void idxp_channel_close(IdxpChannel *channel);
EXPORT bool idxp_channel_greeted(IdxpChannel *channel);
EXPORT int idxp_channel_get_roleid(char *stype, char *role);
EXPORT bool idxp_channel_get_bool_data(IdxpChannel *channel,char *key);
EXPORT void idxp_channel_set_bool_data(IdxpChannel *channel,char *key, bool value);
EXPORT bool idxp_connection_is_ok(IdxpConnection *connection);
//Frame & Msg related functions
EXPORT IdxpFrame *idxp_channel_send_msg_and_wait(IdxpChannel *ch,cchar *msg);
EXPORT bool idxp_channel_send_msg(VortexChannel *ch,cchar *msg);
EXPORT char *idxp_frame_get_payload(IdxpFrame *frame);
//Broadcast related functions
EXPORT IdxpPeer *idxp_broadcast_peer_create(IdxpConnection *connection, IdxpChannel *channel, int channel_type);
EXPORT IdxpPeer *idxp_broadcast_peer_headinsert(IdxpPeer *toplist, IdxpPeer *to_insert);
EXPORT IdxpPeer *idxp_broadcast_peer_delete(IdxpPeer *toplist, IdxpPeer *to_delete);
EXPORT IdxpPeer *idxp_broadcast_peer_channeltype(IdxpPeer *to_change, int channel_type);
EXPORT void idxp_broadcast_send_message(int channel_type ,const char *msg);
EXPORT IdxpPeer *idxp_broadcast_peer_from_channel(IdxpPeer *toplist, IdxpChannel *channel);
EXPORT IdxpPeer *idxp_broadcast_peer_toplist(IdxpPeer *peer);

/*
	BACKEND Functions
*/
//RECEIVE Handlers
void RECEIVE_greeting(VortexChannel *channel,VortexConnection * connection,VortexFrame *frame,axlPointer user_data);
void RECEIVE_heartbeat_client(VortexChannel *channel,VortexConnection * connection,VortexFrame *frame,axlPointer user_data);
void RECEIVE_heartbeat_server(VortexChannel *channel,VortexConnection * connection,VortexFrame *frame,axlPointer user_data);
void RECEIVE_config_client(VortexChannel *channel,VortexConnection * connection,VortexFrame *frame,axlPointer user_data);
void RECEIVE_config_server(VortexChannel *channel,VortexConnection * connection,VortexFrame *frame,axlPointer user_data);
void RECEIVE_alert_client(VortexChannel *channel,VortexConnection * connection,VortexFrame *frame,axlPointer user_data);
void RECEIVE_alert_server(VortexChannel *channel,VortexConnection * connection,VortexFrame *frame,axlPointer user_data);
void RECEIVE_extended_client(VortexChannel *channel,VortexConnection * connection,VortexFrame *frame,axlPointer user_data);
void RECEIVE_extended_server(VortexChannel *channel,VortexConnection * connection,VortexFrame *frame,axlPointer user_data);

bool START_generic(int channel_num,VortexConnection *connection,axlPointer user_data);
bool idxp_channel_onclose(int channel_num, VortexConnection *connection, axlPointer user_data);
void idxp_init_framehan(void);
bool default_custom(IdxpConnection *connection,IdxpChannel *channel,IdxpFrame *frame);

// Roles & Streamtypes ENVIRONMENTS
void idxp_environment_heartbeat_client(IdxpChannel *channel,IdxpConnection *connection,axlPointer user_data);
void idxp_environment_heartbeat_server(IdxpChannel *channel,IdxpConnection *connection,axlPointer user_data);
void idxp_environment_alert_client(IdxpChannel *channel,IdxpConnection *connection,axlPointer user_data);
void idxp_environment_alert_server(IdxpChannel *channel,IdxpConnection *connection,axlPointer user_data);
void idxp_environment_config_client(IdxpChannel *channel,IdxpConnection *connection,axlPointer user_data);
void idxp_environment_config_server(IdxpChannel *channel,IdxpConnection *connection,axlPointer user_data);
void idxp_environment_extended_client(IdxpChannel *channel,IdxpConnection *connection,axlPointer user_data);
void idxp_environment_extended_server(IdxpChannel *channel,IdxpConnection *connection,axlPointer user_data);
void idxp_environment_destroy_heartbeat_client(IdxpChannel *channel);
void idxp_environment_destroy_heartbeat_server(IdxpChannel *channel);
void idxp_environment_destroy_alert_client(IdxpChannel *channel);
void idxp_environment_destroy_alert_server(IdxpChannel *channel);
void idxp_environment_destroy_config_client(IdxpChannel *channel);
void idxp_environment_destroy_config_server(IdxpChannel *channel);
void idxp_environment_destroy_extended_client(IdxpChannel *channel);
void idxp_environment_destroy_extended_server(IdxpChannel *channel);




// Greeting Related Functions
char *idxp_greeting_get_prop(xmlNode *this,const char *prop,char dst[MAX_STRING_SIZE]);
// Heartbeat Related Functions
VortexThreadFunc idxp_heartbeat_sender(axlPointer user_data);
VortexThreadFunc idxp_heartbeat_receiver(axlPointer user_data);
EXPORT char *idmef_create_heartbeat(char *message_id,char *Analyzer_id,int interval,xmlNode *nodeContent,xmlNode *AddData);
extTime *get_extended_timestamp(void);
EXPORT char *idxp_timestamp_hex(void);
//DTD Related Functions
void	idxp_dtd_error_log(void * ctx, const char * msg, void *el);
// TLS-SASL Related Functions
bool check_and_accept_tls_request(VortexConnection *connection,char *serverName);
bool on_accepted(VortexConnection *connection,axlPointer data);
char *certificate_file_location(VortexConnection *connection,char *serverName);
char *private_key_file_location(VortexConnection *connection,char *serverName);
VortexSaslAuthCramMd5 sasl_cram_md5_validation(VortexConnection *connection,const char *auth_id,const char *authorization_id,const char *password);



int Localtime_m(struct tm *_Tm, time_t *_Time);
#endif

